Принципы объектно-ориентированного программирования

         

ASP.NET и Web-формы

Технология ASP.NET, предназначенная для создания Web-приложении, является важной частью платформы .NET. По сравнению с очередной усовершенствованной версией ASP (Active Server Pages — Активные страницы сервера), эта новая технология представляет собой более унифицированную платформу, которая значительно упрощает реализацию сложных Web-приложений В данной главе мы ознакомимся с основами технологии ASP.NET, а также рассмотрим Web-формы, облегчающие создание интерактивных Web-страниц. В главе 11 "Web-службы" мы изучим построение Web-служб на основе технологии ASP.NET. Web-службы позволяют создавать Web-приложения, которые могут совместно обрабатывать данные, будучи развернутыми в неоднородных (гетерогенных) системах В главе 12 "Web-узлы и Web-службы, работающие на основе ATL Server" иллюстрируется создание Web-страниц и Web-служб на основе сервера ATL Server.



Что такое ASP.NET?

Изучение технологии ASP.NET мы начнем с рассмотрения очень простого Web-приложения. На примере этого приложения мы изучим систему отладки, используемую при программировании на основе технологии ASP.NET. Кроме того, коротко будут рассмотрены основы обработки данных в Web. Изучая этот маленький пример, мы столкнемся с некоторыми сложными задачами, которые решаются в процессе разработки Web-приложений. Благодаря этому мы сможем по достоинству оценить возможности и преимущества технологии ASP.NET; о них и будет речь в оставшейся части данной главы



Основные принципы создания Web-приложения

Web-приложение состоит из страниц с документом и страниц с кодом Документ и код хранятся в своем собственном формате Простейшим документом является статическая HTML-страница. Она содержит информацию, которая будет отформатирована и затем отображена Web-броузером. HTML-страница может также содержать гиперссылки на другие HTML-страницы. Гиперссылка (или просто ссылка) содержит адрес, либо унифицированный указатель информационного ресурса (Uniform Resource Locator — URL), определяющий местонахождение искомого документа. Объединение информации, которая формирует страницу, и ссылок иногда называют гипертекстом. С помощью гипертекста обеспечивается удобство навигации в безбрежном океане информации, которая содержится во всемирной паутине (World Wide Web — WWW)

Поддержка управляемого C++в ASP.NET

Управляемый С+-Ь поддерживается технологией ASP.NET лишь частично. Сценарий ASP.NET, написанный на некоторых других языках платформы .NET, например на С# или VB.NET, может быть внедрен ' в Web-страницу. Такой сценарий динамически компилируется в процессе выполнения приложения. Однако использовать управляемый C++ для написания внедряемых сценариев ASP.NET нельзя. На управляемом C++ можно писать лишь предварительно компилируемые сборки, которые используются ASP.NET-странидей. Такие ASP.NET-страницы называют страницами с "предварительно компилируемым фоновым кодом" ("precompiled code-behind"). Инструментальные средства разработки графического интерфейса пользователя (Graphical User Interface, GUI) Web-страниц на основе ASP.NET, входящие в состав среды Visual Studio.NET, позволяют генерировать код на С# и VB.NET. Код на C++ они не генерируют. Тем не менее, практически все элементы пользовательского интерфейса могут быть реализованы на C++, но при этом соответствующий код нужно писать самостоятельно.

Установка примеров web-приложений

Как обычно, все примеры программ, которые рассматриваются в данной главе, расположены в папке, соответствующей данной главе. Но прежде чем вы сможете запустить программу, вам необходимо инсталлировать информационный сервер Internet (Internet Information Services— US) на вашей машине. Информационный сервер Internet инсталлируется по умолчанию вместе с операционной системой Windows 2000 Server. Если на вашей машине установлена операционная система Windows 2000 Workstation, информационный сервер Internet придется инсталлировать отдельно. После инсталляции информационного сервера Internet, вы получите доступ к его описанию с помощью броузера Internet Explorer. Для этого используйте унифицированный указатель информационного ресурса (URL) http: //localhost. В окне броузера откроется начальная страница документации информационного сервера Internet (рис. 10.1).



Рис. 10.1. Описание информационного сервера Internet (Internet Information Services — US)



Рис. 10.2. Диспетчер служб Internet (Internet Services Manager)



Рис. 10.3. Создание виртуального каталога

Средством управления информационного сервера Internet является диспетчер служб Internet (Internet Services Manager) — интегрируемый модуть пульта управления Microsoft (Microsoft Management Console, MMC). Он находится в папке Administrative Tools (Средства администрирования) Панели управления (Control Panel). На рис. 10.2 показано главное окно диспетчера служб Internet (Internet Services Manager). Чтобы запустить или остановить работу Web-сервера, а также выполнить некоторые другие задачи, следует щелкнуть правой кнопкой мыши на элементе Default Web Site. Чтобы выполнить конфигурацию Web-сервера, нужно выбрать из контекстного меню команду Properties (Свойства).
По умолчанию Web-файлы, предназначенные для публикации, хранятся в катаюге \Inetpub\wwwroot. Он находится на том же логическом диске, на котором инсталлирована операционная система Windows. Диспетчер служб Internet (Internet Services Manager) позволяет переопределить этот каталог. Чтобы получить доступ к Web-страницам, расположенным в любом каталоге вашего жесткого диска, необходимо создать на его базе виртуальный каталог Проще всего это сделать в Проводнике Windows (Windows Explorer) Щелкните правой кнопкой мыши на нужном кататоге. Из контекстного меню выберите пункт Sharing (Совместное использование) Затем перейдите на вкладку Web Sharing (Совместное использование в Web), щелкните на кнопке Add (Добавить) и введите альтернативное имя (псевдоимя, или псевдоним). Альтернативное имя будет использоваться в качестве имени виртуапьного каталога. На рис. 10.3 иллюстрируется создание псевдоимени NetCpp для виртуального кататога на основе кататога \Ol\NetCpp\ChaplO. Для того чтобы можно было выполнять дальнейшие примеры, иллюстрирующие материал данной главы, создайте этот виртуальный каталог на вашей машине сейчас



Рис. 10.4. Начатьная страница, содержащая ссьпки на примеры ASP .NET-программ

Создав виртуальный каталог, вы получите доступ к хранящимся в нем файлам. Для этого следует указать псевдоимя каталога в унифицированном указателе информационного ресурса (URL). В частности, чтобы получить доступ к файлу default.htm, который расположен в созданном виртуальном каталоге, используйте унифицированный указатель информационного ресурса (URL) http: //localnost/NetCpp/. Файл default.htm представляет собой начальную страницу, где содержатся ссылки на все примеры ASP.NET-программ, рассматриваемые в данной главе (рис. 10.4).



Программа на С#: Echo (Эхо)

Первая программа, которую мы рассмотрим в данной главе, называется Hello, aspx. На начальной странице она представлена соответствующей ссылкой. Пример называется "монолитным'', так как он выполнен в виде одного файла. В этот файл вложен код сценария для сервера ASP.NET. Поскольку писать код вложенного сценария на языке C++ нельзя, он написан на С#. На этом примере будет рассмотрена работа приложений с вложенным кодом сценария. Исходный код программы приведен ниже. Это обычный HTML-текст, в который внедрен код определенного сценария, написанный на С#. Кроме того, в нем имеются некоторые специальные тэги, которые распознает ASP. NET, описывающие элементы управления сервера

<!—- Hello.aspx -->
<%@ Page Language="Cft" %>
< !-- Язык Страницы -->
<HTML>
<HEAD>
<SCRIPT RUNAT="SERVER">
<'-- СЦЕНАРИЙ RUNAT = "СЕРВЕР" —>
protected void cmdEcho__Click(obiect Source, EventArgs e)
{
IblGreeting.Text="Hello, " + txtName.Text; // Текст = "Привет", + txtName.Текст;
}
</SCRIPT>
<!-- сценарий -->
</HEAD>
<BODY>
<!-- ТЕЛО -->
<FORM RUNAT="SERVER">Your name:&nbsp;
<asp:textbox id=txtNdme Runat="server"></asp:textbox>
<p><asp: button ld=cmdEcho onclick=cmdEcho_Click Text "Echo" runat="server" tooltip="Click to echo your name">
</asp :buttonx/p>
<asp:label id=lblGreeting runat="server">
</asp:]abcl* <P></P>
</FORM>
</BODY>
<!-- тело -->
</HTML>

Чтобы запустить программу, укажите унифицированный указатель информационного ресурса (URL) http://local.iost/NetCpp/Hello.aspx или шепкните кнопкой мыши на ссылке Hello, aspx, расположенной на начальной странице с примерами программ. Вы увидите страницу с текстовым полем, в которое вы можете ввести свое имя, и кнопкой Echo (Эхо). Введите имя и затем щелкните на кнопке Echo (Эхо) Теперь появится введенное вами имя с предшествующим ему приветствием "Hello" ("Привет"). Пока на экране отображается эта простая форма, вы сможете ввести другое имя. Если указатель мыши расположить над кнопкой Echo (Эхо), в желтом прямоугольнике будет выведена подсказка "Click to echo your name" ("Щеткните, чтобы отобразить ваше имя"). Работа данной программы иллюстрируется на рис. 10.5.
Написание этой маленькой программы при помощи других средств построения Web-приложений, включая ASP (Active Server Pages), является не совсем тривиальной задачей. Характерная особенность этого приложения — его пользовательский интерфейс, полностью реализованный на основе формы Пользователь представляется с помощью формы и взаимодействует с этой же формой. Введенные данные обрабатываются сервером, и пользователь продолжает видеть ту же форму. Такая мелеть пользоватетьского интерфейса— вторая сущность настольных приложений. Но в Web-приложениях подобная модель пользовательского интерфейса используется не слишком часто Как правило, Web-сервер отсылает обратно клиенту уже другую страницу. Конечно, для создания приложения с интерфейсом в виде формы можно было бы использовать и технологию наподобие ASP, но код получится несколько громоздким. Ведь серверу пришлось бы синтезировать новую страницу, идентичную старой. Для этого в новую страницу нужно включить тэги, описывающие исходную страницу, а также некоторую отсылаемую клиенту дополнительную информацию (в нашем примере Echo (Эхо) это приветствие, которое выводится внизу страницы) Иными словами, необходим механизм запоминания текущих данных, введенных в элементах управления формы Другая особенность названного Web-приложения состоит в том, что некоторая обработка данных происходит также и на стороне клиента. А именно, броузер выводит подсказку в желтом прямоугольнике Такую расширенную обработку данных в состоянии выполнить броузер Internet Explorer Некоторые другие броузеры эту функцию не поддерживают



Рис. 10.5. Функционирующая программа Hello.asp

Если вы посмотрите на код программы, то убедитесь, что реализовать подобные Web-приложения с помощью ASP.NET совсем несложно (по крайней мере, на языке С# или VB.NET).



Возможности ASP.NET

ASP.NET предоставляет модель программирования и соответствующую инфраструктуру, которая облегчает разработку Web-приложений нового типа. Частыо этой инфраструктуры является среда выполнения платформы .NET и ее каркас .NET Framework Серверная программа пишется на одном из языков программирования платформы .NET, которые компилируются либо предварительно, либо оперативно, т.е в процессе выполнения приложения. ASP.NET поддерживает две основные модели программирования.

Web-формы облегчают создание Web-страниц на основе форм. Среда разработки в режиме полного соответствия WYSIWYG (What You See Is What You Get — что видишь на экране, то и получишь при печати) позволяет просто перетаскивать соответствующие элементы управления на Web-страницу Специальные элементы управления сервера предоставляют программистам модель событий, похожую на модель событий, которая используется при программировании Windows-приложений. В данной главе подробно обсуждаются Web-формы. Web-службы позволяют через программный интерфейс приложения (API) представить на Web-узле функции, которыми могут воспользоваться другие удаленные приложения. Для обмена данными используются стандартные Web-протоколы и форматы, например, протокол передачи гипертекстовых файлов HTTP (Hypertext Transfer Protocol) и язык XML (extensible Markup Language), что позволяет избежать проблем, связанных с прохождением пакетов данных через системы сетевой защиты (брандмауэры). Web-службы обсуждаются в следующей главе

Web-формы и Web-службы могут использовать дополнительные возможности, предоставляемые платформой NET, например, оттранслированные программы и среду выполнения платформы NET. Кроме того, в самой ASP NET предусмотрен ряд служб инфраструктуры, к числу которых принадлежит управление состоянием, защита, конфигурирование, кэширование и трассировка (отладка) программ

Оттранслированные программы

Web-формы (и Web-службы) могут быть написаны на любом языке, который поддерживается платформой .NET и интерпретируется верхним слоем общеязыковой среды выполнения CLR (Common Language Runtime) К числу таких языков принадлежат С#, VB.NET, и C++ с управляемыми расширениями. Полученная программа затем транслируется За счет этого обеспечивается более высокая производительность по сравнению с ASP-страницами, написанными на интерпретируемом языке сценариев, например, VBScnpt. Оттранслированным программам доступны все дополнительные возможности среды NET, например, управляемая среда выполнения, и, конечно же, библиотека классов .NET Framework. Традиционный неуправляемый код может быть вызван посредством .NET-служб, обеспечивающих возможность взаимодействия управляемого и неуправляемого кода. Эти службы обсуждаются в главе 15 "Смешивание управляемого и неуправляемого кода".

Элементы управления сервера

В ASP.NET введено существенное новшество, известное как элементы управления сервера Элементы управления сервера описываются специальными тэгами, например <asp:textbox>. Серверная программа взаимодействует с элементами управления сервера. Затем среда выполнения ASP.NET генерирует обычную HTML-страницу, которая отсылается Web-броузеру. С помощью такой модели программирования легко получить стандартный HTML-код. Этот код может быть интерпретирован любым броузером.

Независимость кода от броузеров

Всемирная сеть (World Wide Web — WWW) построена на стандартах, но используемые броузеры не полностью совместимы. Некоторые из них поддерживают специфические функции и это является неутешительным житейским фактом. Перед дизайнером, создающим Web-страницу, открываются две, не очень-то привлекательные, возможности: писать простейший код, понятный каждому броузеру, или писать индивидуальный код для каждого броузера Использование элементов управления сервера позволяет существенно облегчить решение этой проблемы. ASP.NET учитывает совместимость броузеров на этапе генерации кода элементов управления сервера. Если страница запрошена мощным многофункциональным броузером, тогда генерируется HTML-код, использующий дополнительные функции броузера. В противном случае генерируется простейший HTML-код. Возможности используемого броузера ASP.NET определяет автоматически.

Отделение кода от содержимого

Стандартные ASP-страницы представляют собой смесь кода сценариев и элементов языка HTML. В ASP.NET код сценариев четко отделен от представляемого содержимого. Если код сценария написан на языке, который поддерживает создание вложенных сценариев ASP.NET, например, на С# (но не на C++), тогда этот код можно заключить в блок <SCRIPT RUNAT="SERVER"> ... </SCRlPT>. Или, что еще лучше, код сценария можно разместить на отдельной, так называемой, странице с "фоновым кодом". Именно таким образом следует поступить, если код сценария написан на C++. Страницы с "фоновым кодом" обсуждаются в следующей, основной части данной главы.

Управление состоянием

Протокол передачи гипертекстовых файлов (HyperText Transfer Protocol — HTTP) не хранит информацию о состоянии страницы. Это означает следующее. Пусть пользователь ввел в элементы управления формы некоторую информацию и отослал заполненную форму на сервер. Еспи затем форма отобразится снова, то введенная пользователем информация, как правило, будет потеряна. Чтобы сохранить информацию, введенную пользователем, в Web-приложение нужно добавить специальный код, который запоминает состояние формы. В ASP.NET сохранение этих составляющих частей состояния страницы полностью прозрачно. В ASP.NET также имеются удобные средства управления состоянием другого сеанса и состоянием приложения.



Архитектура Web-форм

Web-форма состоит из двух частей:

отображаемого содержимого, или презентации формы. Как правило, отображаемое содержимое описывается на языке HTML; программного кода, который описывает логику взаимодействия с визуальными элементами.

Физически Web-форма представлена файлом с расширением . aspx. Расширение любой HTML-страницы можно изменить на .aspx. При этом представление страницы с новым расширением будет тождественно представлению исходной страницы. Иными словами, Web-формы совместимы снизу вверх с обычными HTML-страницами.
Особенность Web-форм состоит в способе, при помощи которого программный код отделяется от самой формы. Исходный код (написанный не на C++) может храниться в отдельном не скомпилированном файле. Или же программный код (снова таки, не на C++) может быть вложен в . aspx-файл. И, наконец, код (написанный на С#, VB или C++) может храниться в предварительно скомпилированной сборке, содержащей динамически подключаемую библиотеку (DLL). Когда страницы загружаются Web-сервером, выполняется код, описывающий пользовательский интерфейс. Этот код динамически формирует отображаемую клиентом страницу.
Чтобы четче представить архитектуру Web-форм, написанных на C++, мы рассмотрим пример HelloCodebehind. Эта программа отображает информацию, введенную пользователем. Чтобы запустить приложение, введите в адресной строке броузера унифицированный указатель информационного ресурса (URL) http: //localhost/NetCpp/HeiloCodebehind. aspx. Код, написанный на C++, содержится в файле HelloCodebehind.aspx.h. Обратите внимание, что данный проект создает динамически подключаемую библиотеку (DLL) — файл HelloCcdebehind.dl]. Эта динамически подключаемая библиотека (DLL) затем копируется в подкаталог bin виртуального каталога. (Виртуальный каталог мы создали раньше для хранения примеров программ, которые рассматриваются в главе 10 "ASP.NET и Web-формы". Так было сделано потому, что информационный сервер Internet (US) ищет загружаемые динамически подключаемые библиотеки (DLL) в этом подкаталоге.) Код, который описывает видимые эпементы страницы (презентацию страницы), приведен ниже. Он содержится в файле HelloCodebehind.aspx:

<!-- KelloCoaebehind.aspx -->
<%@ Assembly Name=" HelloCodebehind" °>
<!-- Имя сборки -->
<%@ Page Inherits= MyWebPage ">
<HTML>
<HEAD>
</HEAD>
<BODY> <!-- ТЕЛО -->
<FORM RUNAT="SERVER">YOUR NAME:&nbsp;
<asp:textbox id=txtName Runat="server"></asp:textbox>
<p>asp:button id=cmdEcho onclick=cmdEcho__Click Text="Echo"
runat="server" tooltip="Click to echo your name">
</asp :buttonx/p>
<asp:lacel id=lblGreeting runat="server">
</asp:label>
<P></P>
</FORM>
</BODY>
<!-- тело -->
</HTML>
Код, который создает интерфейс пользователя, содержится в файле HelloCodebehind. h:
//HelloCodebehind.h
fusing <System.dll>
fusing <System.Web.dll>
using namespace System;
// использование пространства имен Система;
using namespace System::Web;
// использование пространства имен Система::Сеть;
using namespace System::Web::UI;
// использование пространства имен
// Система::Сеть:пользовательский интерфейс;
using namespace System::Web::UI::WebControls;
// использование пространства имен
// Система::Сеть::Пользовательский интерфейс::WebControls;
public _gc class MyWebPage : public System::Web::UI::Page
// класс сборщика мусора MyWebPage : общедоступная Система::
// Сеть:: Пользовательский интерфейс:: Страница
{
protected: // защищенный
TextBox *txtName;
Button *cmdEcho; // Кнопка
Label *lblGreeting; // Метка
public:
void cmdEcho_Click(Object *Source, EventArgs *e)
{
IblGreeting-XText = // Текст
String::Format( // Строка:: Формат "Hello, (0).
Welcome to Managed C++ ASP.", // "Привет, {О}. Добро пожаловать
// в Управляемый C++ ASP. ",
txtName->Text); // Текст
}
};

Этот код нужно скомпилировать отдельно и развернуть полученную сборку HelloCodebehind. dll в каталоге \OI\NetCpp\ChaplO\bin. Информационный сервер Internet (US) автоматически ищет загружаемые файлы в подкаталоге bin виртуального каталога.



Класс Page (Страница)

Ключевым (базисным) пространством имен для Web-форм и Web-служб является пространство имен System: :Web (Система::Сеть). Поддержка Web-форм реализована в пространстве имен System: :Web: :UI (Система::Сеть::Пользовательский интерфейс). Поддержка элементов управления сервера, например текстовых полей и кнопок, реализована в пространстве имен System: :Web: :UI: :WebControls (Система::Сеть:: Пользовательский интерфейс:^еЬСоп1го1$). Выходная . aspx-страница динамически генерируется классом Page (Страница) пространства имен System: :Web: :UI (Система::Сеть::Пользовательский интерфейс), а также классами, производными от класса Page (Страница), что иллюстрируется на примере последней рассмотренной нами страницы с фоновым кодом.

Наследование от класса Page (Страница)

Выходная страница генерируется в результате взаимодействия элементов, которые содержатся в .aspx-файле, кода, который содержится в файле с фоновым кодом (или сценария в случае С# или VB.NET) и базового класса Page (Страница). Возможность такого взаимодействия обеспечивает ASP.NET. Для .aspx-файла ASP.NET динамически создает класс, производный от класса, реализованного с помощью фонового кода или сценария, который, в свою очередь, является производным от класса Page (Страница). Иерархия классов, производных от класса Page (Страница) показана на рис. 10.6. Созданный нами класс MyWebPage является производным от класса Page (Страница).



Рис. 10.6. Иерархия классов, производных от класса Page (Страница)

Последним потомком (листом) класса Page (Страница) является класс My .aspx Page (рис. 10.6). Он динамически создается средой выполнения ASP.NET. Данный класс расширяет возможности класса MyWebPage (рис. 10.6). Он объединяет элементы управления и HTML-текст Web-формы. В результате компиляции данного класса создается исполняемый модуль. Когда страницу запрашивает броузер, загружается этот модуль. Он создает HTML-страницу, которая затем отсылается броузеру.



Время существования страниц с Web-формами

Чтобы четко представить и глубоко понять архитектуру Web-форм, мы рассмотрим, что происходит во время существования простого приложения HelloCodeBehind, реализованного на C++. В этом приложении используется предварительно скомпилированный файл HelloCodebehind. aspx, который содержит фоновый код. Исходный код файла написан на C++. Если используется другой язык, тогда компилировать файл не нужно. Достаточно лишь иметь файл с исходным фоновым кодом. То, что происходит во время существования Web-формы, которая использует предварительно скомпилированный фоновый код, можно описать следующим образом.
1. Приложение запрашивает WеЬ-страницу HelloCodebehind. aspx посредством броузера.
2. Среда выполнения ASP NET создает класс Page (Страница), производный от класса реализованного в предварительно скомпилированной сборке В этом классе объединены визхальные элементы, которые содержатся в aspx-файле, и код, содержащийся в предварительно скомпилированной сборке Затем класс компи-лирхется и выполняется Резхльтатом выполнения является HTML-страница, которая отсылается Web-броузеру Чтобы увидеть HTML-код в броузере Internet Explorer в меню View (Вид) выберите команду Source (В виде HTML) Проделав это, вы \бедитесь что э шменты управления сервера заменены обычным HTML-кодом Он приведен ниже
3. Броузер интерпретирует HTML-код и отображает простую форму (рис. 10.7) Чтобы отличить этот пример от аналогичного ему первого примера этой главы, фраза "YOUR NAME" (' ВАШЕ ИМЯ') отображается прописными (заглавными, большими) буквами Поскольку форма отображается впервые, текстовое поле еще не зшолнено и отсутствует приветствие
4. Потьзователь вводит свое имя например Peter и щелкает на кнопке Echo (Эхо) Броузер распознает, что была нажата кнопка Submit (Отослать) Форма использует метод post ("отправить почтовое сообщение") и выполняет действие "HelloCodebehind aspx" Таким образом, мы отправили в первоначальный aspx-фаил 'почтовое сообщение с уведомлением"
5. Теперь сервер обрабатывает страницу В этот раз событие было инициировано щелчком пользователя на кнопке Echo (Эхо) Дальше вызывается обработчик события из класса MyWebPage



Рис. 10.7. Форма приложения Echo (Эхо) отображается впервые

6. Для считывания имени, введенного пользоватепем, применяется свойство Text (Текст) элемента управления сервера txtName (тип TextBox (Текстовое поле)) Далее формируется строка с приветствием, которая затем присваивается этемент> управления lolGreeting (тип Label (Надпись)) При этом снова испотьзуется нотация для свойства
7. Сервер снова генерирует стандартный HTML-код для элементов управления сервера и отсылает полный ответ броузеру Ниже приведен окончательный HTML-код

<fcrm rame="ctrlO" method="post" action="HelloCodebehind.aspx" id="ctrl()">
< i-- действие "nelloCodebehind Qspx" идентификатор - "ctrl()" -->
<input type="hidden" narae="_VIEWSTATE"
value="dDw2MkzODE3NTtOPDtsPGk8M]47P . . +0z4+0z4=" />
YOUR NAME:&nbsp;
<input name="txtName" type="text" value="Peter" id="txtName" />
<p>
<input type="subnu t" name="cmdEcho" value="Echo" id="cmdEcho" title="Click to echo your name">
<-/p>
<ьрап id="lblGreeting">
Hello, Peter. Welcome to Managed C++ ASP.NET
</span> <P></P> </form>

8. Броузер воспроизводит страницу (рис. 10.8.) На этот раз отображается также и приветствие



Состояние представления (вида)

Любая информация, которая вводится в форму, "запоминается" Web-сервером Это важное свойство Web-форм Протокот передачи гипертекста HTTP не хранит информацию о состоянии формы Иными словами, сохранение текущего состояния Web-формы происходит не автоматически, а должно быть запрограммировано. Информация о состоянии Web-формы называется состоянием представления, или состоянием вида (view state) ASP.NET может с помощью каркаса Framework автоматически сохранять состояние представления (вида) Web-формы. При этом используется "скрытый" элемент управления Для удобства восприятия, значительная часть длинного значения, которое описывает состояние представления формы, в приведенном ниже коде опущена.

<input type="hidden" name="_VIEWSTATE"
value="dDw2M]kzODE3NTtOPDtsPGk8M]47P ... +0z4+0z4=" />

Позже в этой главе мы рассмотрим другие возможности ASP.NET, используя которые можно управлять состоянием сеанса и состоянием приложения.



Рис. 10.8. После полного обхода (на сервер и обратно) на странице отображается приветствие



Модель событий Web-форм

С точки зрения программиста, модели событий Web-форм и Windows-форм очень похожи Именно благодаря этому сходству программирование Web-форм оказывается таким легким Но, по сути, события Web-форм сильно отличаются от событий Windows-форм Самое существенное отличие состоит в том, что события Web-форм инициируются клиентом, а обрабатываются сервером.
Мы уже создали простую форму Она состоит из одного текстового поля и одной кнопки Эта форма не обладает достаточным разнообразием элементов управления для того, чтобы подробно проиллюстрировать обработку событий. Представим себе форму, более насыщенную элементами управления. Пусть она содержит несколько текстовых полей, несколько списков, несколько флажков, кнопок и т.п. Поскольку полный обход (путешествие на сервер и обратно) стоит дорого, не каждое событие вызывает автоматическое обращение к серверу. Элементы управления сервера имеют внутренний набор событий сервера. Возникновение таких событий приводит к автоматическому обращению к серверу. Наиболее часто из этих внутренних событий используется событие щелчка на кнопке Другие события, например выбор элемента из списка, не приводят к немедленному обращению к серверу Такого рода события накапливаются в буфере до тех пор, пока событие щелчка на кнопке не вызовет отправку "почтового" сообщения на сервер. Затем сервер обрабатывает различные события, изменяющие состояние формы, причем последовательность обработки событий произвольная Наконец, после этого обрабатывается и событие щелчка на кнопке.



Обработка страницы

Страница совместно обрабатывается Web-сервером, средой выполнения ASP NET и написанным вами кодом. Класс Page (Страница) содержит ряд событий, с помощью которых можно управлять обработкой страницы. При этом также можно использовать свойства и методы класса Page (Страница). В данной главе возможности класса Page (Страница) будут проиллюстрированы на примере программ Мы рассмотрим лишь некоторые основные возможности. Для получения исчерпывающих сведений обратитесь к описанию каркаса .NET Framework.

События страницы

В процессе стандартной обработки страницы на сервере происходит ряд событий. Фактически эти события определены в базовом классе Control (Элемент управления), и, таким образом, могут быть вызваны также элементами управления сервера. Ниже приведены наиболее значимые события.

Init (Инициализация). Событие возникает на первом этапе жизненного цикла страницы, при ее инициализации Информация о состоянии элементов управления еще отсутствует. Load (Загрузка) Событие возникает на этапе загрузки элементов управления в страницу. На данном этапе уже имеется информация о состоянии представления этих элементов управления. PreRender (Предвыполнение). Событие возникает непосредственно перед воспроизведением (отображением) элементов управления в выходном потоке. Как правило, страница это событие не обрабатывает Тем не менее, оно имеет важное значения для реализации ваших собственных элементов управления сервера. Unload (Разгрузка). Событие возникает тогда, когда элементы управления выгружаются из страницы Записывать ваши собственные данные в выходной поток теперь уже поздно.

Свойства страницы

Класс Page (Страница) имеет ряд важных свойств. Некоторые наиболее полезные свойства приведены ниже.

EnableViewState. Указывает, разрешено ли сохранение состояния представления самой страницы и ее элементов управления Можно получить или установить значение этого свойства. По умолчанию оно принимает значение true (истина), т.е. сохранение состояния разрешено ErrorPage. Указывает страницу, на которую будет перенаправлен броузер, если возникнет непредвиденная исключительная ситуация. IsPostBack. Указывает, загружается страница впервые или повторно. I sValid. Указывает, была ли успешной проверка правильности страницы Request (Запрос). Получает HTTP-объект Request (Запрос), который предоставляет доступ к данным входных запросов, поступающих по протоколу передачи гипертекстовых файлов HTTP. Response (Ответ). Получает HTTP-объект Response (Ответ), который отсылает запрошенные данные броузеру. Session (Сеанс). Получает текущий объект Session (Сеанс), в котором ASP.NET хранит состояние сеанса. Trace (Трассировка). Получает объект TraceContext страницы. В этот объект записывается трассировочная информация.

Пример программы

Чтобы продемонстрировать отдельные возможности, которые используются при обработке страниц, мы расширим нашу программу Echo (Эхо). Сборка Hello-Page имеет ряд обработчиков событий страницы. Для записи простого текста в выходной поток используется свойство Response (Ответ). После возникновения каждого события мы отображаем текущий текст в элементах управления сервера txtName и IblGreeting. Обработчик события Load (Загрузка) выводит текущее значение свойства IsPostBack. Если страница запрашивается впервые, свойство IsPostBack имеет значение false (ложь). Если же страница запрашивается повторно, оно принимает значение true (истина).

<!-- HelloPage.aspx -->
<-d@ Assembly Name = "HelloPage" %>
<V:P Page Inherits=MyHelloPage %>
<HTML>
< HEAD>
</HEAD>
<BODY>
<!-- ТЕЛО -->
<FORK RUNAT="SERVER">Your name:&nbsp;
<asp:textbox id=txtName Runat="server">
</asp:textbox>
<p><asp: button id=cmdEcho onclick=cmdEcho_Click Text="Echo" •runat-"server"
tooitip="Click to echo your name">
<!-- подсказка --> </a.-;p : bu11оn></p>
Greeting runat = "server "></asp : label>
</FORMi>
</Body>
< !-- тело -->
</HTML>

В .aspx-файле, который приведен выше, имеется ссылка на сборку HelloPage. Названная сборка содержит класс MyHelloPage. В этом файле также указано, что класс r.vj'.' (Страница) является производным от класса MyHelloPage. Это означает, что события данной страницы обрабатываются методами класса MyHelloPage.
Если страница запрашивается впервые, текстовые поля и подписи не содержат никаких значений, поскольку никакой информации в форму мы еще не вводили. Свойство IsPostBack имеет значение false (ложь). Теперь введите имя Robert (Роберт), и щелкните на кнопке Echo (Эхо). Обработчики событий страницы выведут следующую информацию:

Page_Init
txtName =
IblGreeting =
Page_Load
IsPostBack = True // Истина
txtName = Robert // Роберт
iblGreeting =
Page_PreRender
txtName = Robert // Роберт
IblGreeting = Hello, Robert. Welcome again
// Привет, Роберт. Добро пожаловать снова

В функции Page_Init элементы управления не содержат никаких данных, поскольку состояние представления на этапе инициализации страницы не доступно. В функции Page_Load текстовое поле содержит данные. Надпись не содержит никаких данных, так как обработчик события (щелчка мыши) еще не вызван. Свойство IsPostBack теперь имеет значение true (истина). В функции Page_PreRender оба элемента управления содержат данные.
Щелкните на кнопке Echo (Эхо) еще раз. Данные в элементах управления функции Page_Init опять отсутствуют. А вот в функции Page_Load оба элемента управления используют данные состояния представления. На рис. 10.9 представлено окно броузера, в котором отображено то, что после второго щелчка на кнопке Echo (Эхо) вывели обработчики события страницы.



Рис. 10.9. Вывод броузера после второго щелчка на кнопке Echo (Эхо)

Директива Page (Страница) и директива Assembly (Сборка)

Файл с расширением . aspx может содержать директиву Assembly (Сборка) и директиву Page (Страница). Директива Assembly (Сборка) связывает уже существующую скомпилированную сборку с текущей страницей. Директива Page (Страница) определяет различные атрибуты, которые управляют обработкой ASP.NET-страницы. Каждая директива содержит одну или несколько пар атрибут/значение. Синтаксис директивы Assembly (Сборка) и директивы Page (Страница) приведен ниже.

<@ Assembly Name="HelloCodebehind" @>
<@ Page Inherits=MyWebPage @>

Программа HelloCodebehind.aspx служит примером .aspx-страницы, в которой отсутствует код сценария. Если использовать другие языки программирования, например, С# или VB.NET, сценарий можно вложить непосредственно в . aspx-файл. В таком случае использовать директиву Assembly (Сборка) нет необходимости. Указанные языки программирования также позволяют использовать файлы с фоновым исходным кодом. Для этого в директиве Page (Страница) используется атрибут Src, который указывает на нескомпилированный исходный файл. Язык C++ такие возможности не поддерживает. Если используется язык C++, директива Assembly (Сборка) должна содержать атрибут Name (Имя), который идентифицирует скомпилированную сборку. При помощи атрибута Inherits (Наследуется) указывается класс, производный от класса Page (Страница), производным от которого в свою очередь является класс данной . aspx-страницы.



Трассировка

Технология ASP.NET предоставляет широкие возможности для трассировки программы. Если атрибуту Trace (Трассировка) страницы присвоить значение true (истина), то выходная трассировочная информация, генерируемая ASP.NET, будет выводиться в окне броузера. Кроме того, можно вывести свою трассировочную информацию. Для этого используется метод Write (Запись) объекта TraceContext. Чтобы получить доступ к этому методу, используется свойство Trace (Трассировка) класса Page (Страница).
Страница HelloTrace.aspx иллюстрирует использование трассировки при записи информации в объект Response (Ответ).

<!—- HelloTrace.aspx -—>
<%@ Assembly Name="HelloTrace" %>
<%@ Page Inherits=MyHelloTrace Trace = "true" %>
<!-- Трассировка Страницы --> <HTML>
<HEAD>
</HEAD>
<BODY> <!— ТЕЛО —>
<FORM RUNAT="SERVER">Your name:&nbsp;
<asp:textbox id=txtName Runat="server"> </asp:textbox>
<p><asp:button id=cmdEcho onclick=cmdEcho_Click Text="Echo" runat="server"
tooltip="Click to echo your name">
<!-- подсказка -->
</asp:button></p>
<asp:label id=lblGreeting runat="server">
</asp:label> <P></P>
</FORM>
</BODY> <!-- тело -->
</HTKL>

Класс MyHelloTrace, реализованный в виде сборки rielloTrace.dll, содержит следующий код, который записывает вывод трассировки:

void Page_Init(Gtoect *senaer, EventArgs *e)
{
Page *p = dynamic_cast<Page *>(sender);
// Страница "р = dynarpic__cast <Страница *> (отправитель);
TraceContext *trace = p->get_Trace();
trace->Write("Page_Init<br>"); // трассировка-> Запись
tгасе->Write (String::Concat(
// трассировка-> Запись (Строка)
"txtName = ", txtName->Text, "<br>")); // Текст
trace->Wnte (String: :Concat (
// трассировка-> Запись (Строка)
"IblGreeting = ",iblGreeting->Text, "<br>")); // Текст
}
void Page_Load(Object *sender, EventArgs *e)
{
Page *p = dynamic__cast<Page *>(sender);
// Страница *р = dynamic_cast <Страница *> (отправитель);
TraceContext *trace = p->get_Trace();
trace->Write("Page_Load<br>"); // трассировка-> Запись
trace->Write (String: :Format(
// трассировка-> Запись (Строка:: Формат )
"IsPostBack = (0}<br>", _box (IsPostBack) )
};
trace->Write(String::Concat(
// трассировка-> Запись (Строка)
"txtName = ", txtName->Text, "<br>")); // Текст
trace->Write(String::Concat(
// трассировка-> Запись (Строка)
"IblGreeting = ", lblGreeting->Text, "<br>")); // Текст
}
void Page_PreRender(Object ^sender, EventArgs *e) -
{
Page *p = dynamic_cast<Page *>(&ender);
// Страница *р = aynamic_cast <Страница *> (отправитель);
TraceContext wtrace = p->get_Trace();
trace->Write("Fage_PreRendei<br>"); // трассировка-> Запись
trace->Wnte (String: : Concat
// трассировка-> Запись (Строка)
"txtName == ", txtName->Text, "<br>")); // Текст
trace->Write(String::Concat(
// трассировка-> Запись (Строка)
"IblGreeting = ", lblGreeting->Text, "<br>")); // Текст
}

На рис. 10.10 показано, что отображает броузер после первого запроса данной страницы Обратите внимание, что вывод трассировки и трассировочная информация, генерируемая ASP.NET, отображается после формы



Рис. 10.10. Броузер отображает трассировочную информацию



Программирование запросов и ответов

Архитектура элементов управления сервера строится на верхнем слое более фундаментальной архитектуры обработки данных, которую можно назвать архитектурой запросов и ответов. Понимание запросов и ответов протокола передачи гипертекстовых файлов HTTP поможет нам получить целостное представление о технологии ASP NET Кроме того, при программировании иногда возникают такие ситуации, когда использование запросов и ответов является естественным подходом



Класс HttpRequest

Пространство имен System: :Web (Система Сеть) содержит потезнын класс HttpRequest. Данный класс используется для считывания различных значении, которые клиент отсылает в запросе по протоколу передачи гипертекстовых фантов HTTP Эти значения, принимаемые по протоколу передачи гипертекстовых фантов HTTP, затем будут использованы классическими (те использующими общий шлюзовой ишер-фейс CGI (Common Gateway Interface)) программами или программами, использующими интерфейс прикладного программирования Internet-сервера ISAPI (Internet Server API), которые обрабатывают Web-запрос. На этой основе строится обработка данных на более высоком уровне. В табл. 10.1 приведены некоторые наиболее часто используемые свои-ства класса HttpRequest. Если вы знакомы с протоколом передачи гипертекстовые файлов HTTP, смысл этих свойств должен быть вам понятен Исчерпывающая инфор мация об этих и других свойствах класса HttpRequest содержится в документации по .NET Framework.
Свойство Request (Запрос) класса Page (Страница) возвращае! объект 'tt; quest. Из свойств объекта HttpRequest можно извлечь любую необходимую информацию. Например, следующий код (этот код не содержится ни в одном примере) определяет длину (в байтах) содержимого, отосланного клиентом, и записывает поточенную информацию в объект Response (Ответ). Затем эта информация отображается в окне-броузера.
Таблица 10.1. Общедоступные свойства экземпляра класса HttpReguest

Свойство Смысл
AcceptTypes Строковый массив принимаемых клиентом MIME-типов
Browser (Броузер) Информация о возможностях броузера клиента
ContentLength Длина (в байтах) содержимого, отосланного клиентом
Cookies (Небольшие фрагменты данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, автоматически создаваемые сервером на машине пользователя) Коллекция небольших фрагментов данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, автоматически создаваемых сервером на машине пользователя (cookies), отосланных клиентом
Form (Форма) Коллекция переменных формы
Headers (Заголовки) Коллекция заголовков для протокола передачи гипертекстовых файлов HTTP
HttpMethod Метод передачи по протоколу передачи гипертекстовых файлов HTTP, используемый клиентом (например, СЕТ (Получить) или POST (Отправить почтовое сообщение))
Params Объединенная коллекция, которая состоит из элементов Querystnng, Form (Форма), Server-Variables И Cookies (Небольшие фрагменты данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, автоматически создаваемые сервером на машине пользователя)
Path (Путь) Виртуальный запрос текущего пути
OueryString Коллекция строковых переменных запроса, посылаемого по протоколу передачи гипертекстовых файлов HTTP
ServerVanables Коллекция переменных Web-сервера

Page *p = dynamic_cast<Page *>(sender);
// Страница *р = dynamic_cast <Страница *> (отправитель);
HttpRequest *request = p->get_Request();
int length = request->ContentLength; // длина
HttpResponse *response = p->get_Response();
response->Write(String::Format( // ответ-> Запись (Строка:: Формат
"ContentLength = {0}<br>", _box(length))); // длина

Коллекции

Многие полезные коллекции представлены как свойства объекта HttpRequest. Эти коллекции принадлежат типу NamedValueCollection (в пространстве имен System: :Collections: :Specialized (Система::Коллекции::Специализированное пространство имен)). Получить значение переменной из коллекции можно при помощи строкового ключа. Например, следующий код извлекает из коллекции ServerVan-ables значение переменных сервера QUERY_STRING и HTTP_USER_AGENT.

Page *p = dynamic_cast<Page *>(sender);
// Страница *р = dynamic_cast <Страница *> (отправитель);
HttpRequest *request = p->get_Request();
HttpResponse *response = p->get_Response();
String *strQuery = // Строка
request->ServerVariables->get_Item( // запрос
"QUERY_STRING");
response->Write(String::Format( // ответ-> Запись (Строка:: Формат (
"QUERY_STRING = {0}<br>",strQuery));

String *strAgent = // Строка
request->ServerVariables->get_Item( // запрос
"HTTP_USER_AGENT");
response->Write(String::Format( // ответ-> Запись (
Строка:: Формат ( "HTTP_USER_AGENT = {0}<br>",
strAgent));

Если вслед за унифицированным указателем информационного ресурса (URL) соответствующего .aspx-файла ввести строку запроса ?foo=3, приведенный выше код отобразит в окне броузера что-то примерно следующее:

QUERY_STRING = foo=3
HTTP_USER_AGENT = Mozilla/4.0

Подобные переменные при программировании классического (т.е основанного на общем шлюзовом интерфейсе CGI (Common Gateway Interface)) Web-сервера играют решающую роль. Используя переменные среды, Web-сервер передает информацию CGI-скрипту или программе. На всякий случай ASP.NET обеспечивает доступ и к этой низкоуровневой информации.
Стандартная задача состоит в том, чтобы извлечь информацию из элементов управления формы. В HTML-коде элементы управления идентифицируются атрибутом name (имя). Этот атрибут сервер использует для определения соответствующего значения. Способ передачи данных из формы серверу зависит от того, какой метод использует форма в протоколе передачи гипертекстовых файлов HTTP: GET (Получить) или POST (Отправить почтовое сообщение).
Если используется метод GET (Получить), данные, введенные в форму, кодируются как часть строки запроса. Чтобы затем извлечь нужные значения, используется коллекция QueryString Если же используется метод POST (Отправить почтовое сообщение), данные, введенные в форму, передаются как содержимое после заголовка протокола передачи гипертекстовых файлов HTTP. В этом случае для извлечения значения элементов управления используется коллекция Forms (Формы). Чтобы узнать, какую коллекцию следует использовать, нужно определить значение (GET (Получить) или POST (Отправить почтовое сообщение)) переменной сервера REQUEST_METHOD. (Если переменная REQUEST_METHOD имеет значение GET (Получить), используется коллекция QueryString Если же ее значение равно POST (Отправить почтовое сообщение), используется коллекция Forms (Формы))
Если вы используете ASP NET, тогда вам не стоит волноваться о том, какой метод протокола передачи гипертекстовых файлов HTTP использовался при запросе В ASP NET имеется коллекция Params, которая представляет собой объединение (в математическом смысле) коллекций ServerVariables, QueryString, Forms (Формы) и Cookies (Небольшие фрагменты данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, автоматически создаваемые сервером на машине пользователя)

Пример программы

Идеи, о которых мы рассказали выше, проиллюстрируем на примере простой страницы Squares. aspx Эта страница отображает столбец с квадратами натуральных чисел Числа, квадраты которых будут выведены, ограничиваются значением, вводимым в форме Страница GetSquares aspx отсылает запрос, используя метод GET (Получить), а страница PostSquares.aspx отсылает запрос, используя метод POST (Отправить почтовое сообщение) Пользовательский интерфейс обоих приложений тождественен (рис. 10.11)



Рис. 10.11. Форма, запрашивающая столбец квадратов чисел

Ниже приведен HTML-код страницы GetSquares.aspx Обратите внимание, что мы используем чистый HTML-код И, за исключением директивы Page (Страница), которая используется для включения режима трассировки, признаки использования ASP NET отсутствуют

<! - - GetSquares.aspx - ->
<%@ Page Trace = "false" %>
<!—- Трассировка Страницы --->
<html> <head> </head>
<body> <!-— тело -—>
<P>This program will print a column of square numbers</P>
<!--- Эта программа будет печатать столбец квадратов чисел --->
<form method="get" action = Squares.aspx>
<!--- метод формы = "получить" действие = Squares aspx -->
How many
<!—- Сколько -->
<INPUT type=text size=2 value=5 name=txtCount>
<P></P>
<INPUT type=submit value=Squares name=cmdSquares>
</form>
</body> <!— тело -->
</html>

Тэг form (форма) имеет атрибуты, при помощи которых указывается метод (в данном случае GET (Получить), а не POST (Отправить почтовое сообщение)) и действие (запрос на страницу Squares aspx) Элементы управления имеют атрибут name (имя), с помощью которого сервер извлекает нужное значение
Запустите страницу GetSquares aspx и щелкните на кнопке "Squares" ("Квадраты чисел") Будет отображена некоторая служебная информация, относящаяся к протоколу передачи гипертекстовых файлов HTTP За ней последует столбец с квадратами чисел Поскольку режим трассировки включен, то ASP NET отображает на странице также и подробности запроса На рис 1012 приведены результаты выполнения запроса, в котором используется метод GET (Получить)



Рис. 10.12. Вывод, полученный в результате запроса GET (Получить)

Можно видеть, что данные, введенные в форму, закодированы как часть строки запроса Длина содержимого равна нулю, поскольку используется метод GET (Получить), а не POST (Отправить почтовое сообщение) Если прокрутить трассировочную информацию дальше, можно увидеть еще много интересных сведений Например, там приводится коллекция QueryString
А теперь давайте рассмотрим страницу PostSquares aspx Обратите внимание, — в этот раз тэг form (форма) указывает, что используется метод POST (Отправить почтовое сообщение) Остальные параметры такие же, как и в случае страницы GetSquares . aspx

<!-- postSquares.aspx -->
<%@ Page Trace = "false" %>
<html>
<head>
</head>
<body> <!— тело —>
<P>This program will print a column of squares</P>
<!— Эта программа будет печатать столбец квадратов —>
<form method="post" action = Squares.aspx> How many:
<!— Сколько: —>
<INPUT type=text size=2 value=5 name=txtCount> <P></P>
<INPUT type=submit value=Squares name=cmdSquares> </form>
</body> <i— тело —> </html>

Запустите страницу PostSquares.aspx и щелкните на кнопке Squares (Квадраты чисел) Снова будет отображена некоторая информация, относящаяся к протоколу передачи гипертекстовых файлов HTTP. За ней последует столбец, содержащий квадраты чисел Поскольку режим трассировки включен, то ASP.NET отображает на странице также и подробности запроса. На рис. 10.13 приведены результаты выполнения запроса POST (Отправить почтовое сообщение).



Рис. 10.13. Вывод, полученный в результате запроса POST (Отправить почтовое сообщение)

Поскольку используется метод POST (Отправить почтовое сообщение), то строка запроса пуста Длина содержимого равна 29. Данные, введенные в форму, передаются в текстовом виде вслед за заголовком протокола передачи гипертекстовых файлов HTTP.
Если прокрутить трассировочную информацию дальше, то теперь можно увидеть коллекцию Form (Форма) Именно с помощью этой коллекции ASP.NET обеспечивает доступ к данным, введенным в форме в случае использования метода POST (Отправить почтовое сообщение)


Класс HttpResponse

Класс HttpResponse инкапсулирует информацию ответа, полученного по протоколу передачи гипертекстовых файлов HTTP, притом информация содержится в операции ASP NET Каркас Framework использует данный класс при формировании ответа клиенту. Формирование ответа включает запись элементов управления сервера для отправки клиенту. Созданный вами код сервера может также использовать метод Write (Запись) объекта Response (Ответ). Использование метода Response: :Write (Ответ' Запись) иллюстрировалось уже несколько раз.

Метод Redirect (Переадресовать)

Класс HttpResponse имеет полезный метод Redirect (Переадресовать) Благодаря этому методу сервер может переадресовать запрос, передаваемый по протоколу передачи гипертекстовых файлов HTTP на другой унифицированный указатель информационного ресурса (URL). Простая переадресация, без передачи каких-либо данных, является тривиальной задачей. Все что для этого нужно сделать— это вызвать метод Redirect (Переадресовать) и передать ему требуемый унифицированный указатель информационного ресурса (URL) Примером ситуации, когда используется метод Redirect (Переадресовать), служит реорганизация Web-узла. В процессе реорганизации некоторые страницы могут содержать недостоверную информацию Кроме того, содержимое Web-узла может быть перемещено Чтобы сохранить доступ к старым страницам, достаточно просто переадресовать трафик
Обратите внимание, что при переадресации запроса всегда используется метод GET (Получить) протокола передачи гипертекстовых файлов HTTP Это подобно установлению связи по указанному унифицированному указателю информационного ресурса (URL) (Метод POST (Отправить почтовое сообщение) может использоваться, если данные отсылаются из формы, — тогда можно указать одно из двух действий — GET (Получить) или POST (Отправить почтовое сообщение)) Более интересный случай представляет передача данных на новую страницу. Один из способов передачи данных состоит в том, что передаваемая информация кодируется в строке запроса. При кодировании строки запроса следует придерживаться общепринятых соглашений для протокола передачи гипертекстовых файлов HTTP Класс HttpUtility имеет метод UrlEncode, который корректно кодирует отдельные составляющие элементы строки запроса Вам нужно самостоятельно написать код, который отделяет унифицированный указатель информационного ресурса (URL) от строки запроса при помощи символа "знак вопроса" (9), а также разделяет отдельные составляющие элементы строки запроса при помощи символа "амперсанд" (&).
В папке Hotel (Гостиница) имеется простое Web-приложение, где иллюстрируется использование этого метода передачи данных при переадресации запроса. Файл de fault. aspx содержит форму, при помощи которой собираются данные, необходимые для бронирования мест в гостинице Само бронирование выполняется на странице Reservationl. aspx. Чтобы получить доступ к начальной странице default. aspx, используйте унифицированный указатель информационного ресурса (URL)http://localhost/NetCpp/Hotel/.
Как обычно, ссылка на эту страницу содержится на начальной странице с примерами программ На рис. 10.14 показана начальная страница нашего приложения, которое бронирует место в гостинице
Ниже приведен ASP NET-код на C++, который выполняется после щелчка на кнопке Make Reservation (Забронировать)

void cmdMakeReservation_Click(
Object *sender, EventArgs *e)
{
HttpUtility *utility = new HttpUtility;
String *query = String:.Concat ( // Строка
"City=", utility->UrlEncode(txtCity->Text)); // Город
query = String::Format(
// запрос = Строка:: Формат ( "{0}&Hotel={l}",
query, utility->UrlEncode(txtHotel->Text));
query = String::Format(
// запрос = Строка:: Формат ( "{0}&Date={l}",
query, utility->UrlEncode(txtDate-XText));
query = String::Format( // запрос = Строка:: Формат ( "{0}&NumberDays={1}",
query, utility->UrlEncode(txtNumberDays->Text));
Response->Redirect(String::Concat(
// Ответ-> Переадресовать (Строка:: Concat (
"Reservation!.aspx?", query)); // запрос
}



Рис. 10.14. Начальная страница для бронирования места в гостинице

Метод cmdMakeReservation_Click строит строку запроса. Эта строка присоединяется к унифицированному указателю информационного ресурса (URL) страницы Reservation! .aspx От унифицированного указателя информационного ресурса (URL) ее отделяет символ 9 В качестве разделителя элементов строки запроса используется символ & Для кодирования отдельных элементов используется метод HttpUtility: :UrlEncode Символы "слэш" (в дате) и пробелы, например в названии "San Jose" кодируются отдельно Если щелкнуть на кнопке, будет вызван метод Page_Load класса Reservationl, отображающий страницу, с помощью которой можно забронировать место в гостинице Этот метод считывает название города, название гостиницы, дату и количество дней, которое вы планируете провести в гостинице, а затем отображает полученные данные на возвращаемой Web-странице

void Page_Load(Object *sender, EventArgs *e)
{
Page *p = dynamic_cast<Page *>(sender);
// Страница *р = dynamic_cast <Страница *> (отправитель);
HttpRequest *request = p->get_Request();
HttpResponse *response = p->get_Response() ;
response->Write("Making reservation for ...");
// ответ-> Запись ("Делаю резервирование для ... "};
response->Write("<br>"); // ответ-> Запись
String *city = request->Params->get_Item("City");
// Строка *city = запрос-> Params-> get_Item ("Город");
response->Write(String::Concat("City = ", city));
// ответ-> Запись (Строка:: Concat ("Город = ", город));
response->Write("<br>"); // ответ-> Запись
String *hotel = request->Params->get_Item("Hotel");
// Строка *hotel = запрос-> Params-> get_Item ("Гостиница");
response->Write(String::Concat("Hotel = ", hotel));
// ответ-> Запись (Строка:: Concat
// "Гостиница = ", гостиница));
response->Write("<br>"); // ответ-> Запись
String *strDate = request->Params->get_Item("Date");
// Строка *strDate = запрос-> Params-> get_Item ("Дата");
response->Write(String::Concat("Date = ", strDate));
// ответ-> Запись (Строка:: Concat ("Дата = ", strDate));
response->Write("<br>"); // ответ-> Запись
String *strDays = // Строка
request->Params->get_Item("NumberDays" ) ;
response->Write(String::Concat(
// ответ-> Запись (Строка:: Concat ( "NumberDays = ", strDays));
response->Write("<br>"); // ответ-> Запись
}

Строку запроса можно увидеть в адресной строке броузера На рис. 10.15. показана выходная информация, выводимая броузером (На самом деле, наша программа не бронирует место в гостинице, она всего лишь выводит переданные ей параметры )
Включите трассировку Вывод трассировки продемонстрирует идеи, которые мы обсудили, когда говорили о программировании запросов и ответов в Web-программах В частности, стоит изучить коллекцию Query String, показанную на рис. 10.16.



Рис. 10.15. Вот что выводит броузер после бронирования места в гостинице



Рис. 10.16. Строка запроса используется для того, чтобы передать параметры при переназначении



Изучение конкретного примера

Мы ознакомились с основными возможностями ASP.NET и создали несколько простых Web-страниц, используя шаблоны библиотеки классов управляемого C++. Дальнейшее изучение материала главы 10 "ASP.NET и Web-формы" мы продолжим на конкретном примере. Для языков С# и VB.NET существует специальный шаблон проекта, имеющий название ASP.NET Web Application (Web-приложение на основе ASP.NET), который формирует каркас приложения. Кроме того, конструктор форм (Forms Designer) позволяет легко создавать Web-формы путем перетаскивания необходимых элементов управления с панели инструментов. Конструктор форм (Forms Designer) поддерживает языки С# и VB.NET. Если приложение создается на C++, код соответствующей формы, к сожалению, придется создавать самостоятельно.



Web-страница с информацией о гостиницах

На языке C++ мы создадим простую Web-страницу на основе ASP.NET, на которой отображается информация о гостиницах. Названия городов и гостиниц хранятся в раскрывающихся списках. Выбор названия города в первом раскрывающемся списке приводит к тому, что во втором раскрывающемся списке будут перечислены названия гостиниц, которые расположены в выбранном городе. Информацию о гостиницах содержит компонент Hotel.dll, расположенный в каталоге CaseStudy\AcmeWeb. В свою очередь, этот каталог находится в папке к данной главе. Для заполнения списков мы используем привязку данных. Завершенный проект расположен в каталоге Cas-eStudy\AcmeWeb в папке к данной главе. Вы можете также самостоятельно создать приложение, выполнив все необходимые действия. Сохраните созданное вами приложение в папке Demos (Демонстрации), хранящейся в папке к данной главе.
Чтобы увидеть результаты работы приложения, введите в адресной строке броузера унифицированный указатель информационного ресурса (URL) http://localhost/NetCpp/ CaseStudy/AcmeWeb/AcmeWeb.aspx. Но перед этим еще необходимо создать виртуальный каталог и, используя диспетчер служб Internet (Internet Services Manager), сконфигурировать его в информационном сервере Internet (US) в качестве приложения. Конфигурирование виртуального каталога описывается ниже.

Конфигурирование соединения с Web-сервером

Перед тем как писать приложение, вы, возможно, пожелаете проверить, а, может быть, есть смысл изменить настройки соединения Web-сервера. Имеются два переключателя: File share (Совместное использование файлов) и FrontPage. Если приложение полностью разрабатывается на локальном компьютере, для удобства и ускорения работы рекомендуется выбрать переключатель File share (Совместное использование файлов). Чтобы получить доступ к этому параметру настройки, в меню Tools (Сервис) выберите команду Options (Параметры). Затем выберите папку Projects (Проекты), а в ней — пункт Web Settings (Параметры Web). Наконец, в группе Preferred Access Method (Предпочтительный метод доступа) выберите нужный переключатель. Процесс конфигурации соединения иллюстрируется на рис. 10.17.



Рис. 10.17. При конфигурировании соединения Web-сервера в группе Preferred access method нужно указать предпочтительный метод доступа

Создание сетевого приложения с помощью C++ на основе ASP.NET

1. В Visual Studio в меню File (Файл) выберите команду New (Создать), а затем пункт Project (Проект).
2. В диалоговом окне New Project (Новый проект) в качестве типа проекта (Project Туре) укажите Visual C++ Projects (Проекты на Visual C++). В качестве используемого шаблона (Template) укажите Managed C++ Class Library (Библиотека классов управляемого C++).
3. Укажите AcmeWeb в качестве имени проекта.
4. Укажите путь к проекту С: \OI\NetCpp\ChaplO\Demos (рис. 10.18).
5. Щелкните на ОК При этом в каталоге С: \OI\NetCpp\ChaplO\Demos будут созданы файлы проекта, включая файл решения Acme Web sin
6. Создайте на основе каталога C:\OI\NetCpp\ChaplO виртуальный каталог с псевдонимом NetCpp (рис 10 3), если вы не создали его раньше

Конструирование формы

Поскольку в среде Visual Studio NET конструктор форм не поддерживает язык C++, то форму лучше спроектировать на С#, а затем полученный код (на С#) перенести на язык C++ Сначала вы могли бы создать на С# фиктивный проект с формой и сконструировать саму форму Но это все уже сделано за вас Вы можете воспользоваться файлом WebForml.aspx.h, содержащим готовый код на C++ Он находится в каталоге Cas-eStudy\AcmeWeb Добавьте его в ваш проект, который расположен в каталоге Demo s\AcmeWeb



Рис. 10.18. Создание в среде Visual Studio проекта на основе библиотеки классов C++ (Managed C++ Class Library)

Форма содержит две надписи (Label (Надпись)), два раскрывающихся списка (DropDownList) и одну кнопку (Button) Свойство Text (Текст) первой надписи имеет значения City (Город), а второй — Hotel (Гостиница) Свойство Text (Текст) единственной кнопки имеет значение Make Reservation (Забронировать) Идентификатор (ID) первого раскрывающегося списка принимает значение listCities, второго— listHo-tels Идентификатор (ID) кнопки имеет значение cmdMakeReservation Данная форма представлена на рис. 10.19 Размер раскрывающихся списков, которые показаны на рисунке, был изменен
Чтобы в новом проекте (он расположен в каталоге Demos\AcmeWeb) воспользоваться кодом, перенесенным на C++, (этот код содержится в файле WebForml.aspx.h, хранящемся в папке CaseStudy\AcmeWeb), выполните следующие действия
1. Скопируйте файл WebForml. aspx. h из каталога CaseStudy\AcmeWeb в каталог Demos\AcmeWeb, в котором расположен новый проект
2. Откройте новый проект, если он еще не открыт Для этого войдите в каталог Demos\AcmeWeb идважды щелкните на файле Acme Web. sin



Рис. 10.19. Конструктор форм (Form Designer) позволяет добавлять элементы управления к форме

3. В окне поиска решения (Solution Explorer), щелкните правой кнопкой мыши на узле Header Files (Заголовочные файлы) (Этот узел находится в проекте Acme Web ) Теперь из контекстного меню выберите команду Add (Добавить) и затем Add Existing Item (Добавить существующий элемент) После этого дважды щелкните левой кнопкой мыши на файле WebForml. aspx. h
4. Удалите файл Acme Web. h, который в проекте не используется Для этого выделите этот файл в окне поиска решения (Solution Explorer) и нажмите клавишу Delete (Удалить) Поскольку файл AcmeWeb h больше не требуется вообще, его можно удалить и из каталога \Demos\AcmeWeb С этой целью можно использовать и Проводник Windows (Windows Explorer)
5. Отредактируйте файл AcmeWeb срр Удалите директиву iinclude, которая включает файл AcmeWeb h Добавьте директиву # include, чтобы включить файл WebForml aspx.h Вскоре мы добавим в проект еще один заголовочный файл, который называется Global. азах. h Включите его в текущий файл при помощи директивы #include

// Это - основной файл динамически подключаемой библиотеки (DLL).
#include "stdafx.h"
#include "Global.asax.h"
#include "WebForml.aspx h"

Ниже приведен исходный файл WebForml. aspx. h Обратите внимание, что для извлечения объекта HotelBroker используется статическое поле Global: : hotelBroker Вскоре мы увидим, что этот объект создается методом Application_Start объекта Global (Глобальный), который определен в исходном файле Global. asax. h

//WebForml.aspx.h
namespace AcmeWeb
// пространство имен AcmeWeb
{
public _gc class WebForml :
public System::Web::UI::Page
// класс сборщика мусора WebForml:
// общедоступная Система::Сеть::Пользовательский
// интерфейс::Страница
{
protected: // защищенный
System::Web::UI::WebControls::Label *Labell;
System::Web::UI::WebControls::Label *Label2;
System::Web::UI::WebControls::DropDownList
*listCities; System::Web::UI::WebControls::DropDownList
*listHotels;
private: // частный
static HotelBroker *hotelBroker; // статический
public:
WebForml()
{
Page::Init += new System::EventHandler(
this, Page_Init);
}
private: // частный
void Page_Load(Object *sender, System::EventArgs *e)
{
if ( HsPostBack)
{
hotelBroker = Global:rhotelBroker;
ArrayList *cities = hotelBroker->GetCities();
listCities->DataSource = cities; // города
ArrayList *hotels = hotelBroker->GetHotels;
dynamic_cast<String *> // Строка
(cities->get_Item(0))); // города
BindHotels(hotels); // гостиницы
DataBind();
}
}
};



Привязка данных

Теперь нужно заполнить первый раскрывающийся список (DropDownList) названиями городов. Необходимые для этого данные могут быть получены с помощью метода GetCi-ties объекта HotelBroker. Мы воспользуемся свойством привязка данных (data binding), которым обладает раскрывающийся список. Возможно, вы были уверены, что привязка данных используется исключительно при работе с базами данных. При разработке приложений на основе платформы .NET понятие привязка данных принимает более широкий смысл. Здесь привязка данных используется не только при работе с базами данных, но и с другими источниками данных. Привязка элементов управления к базе данных играет очень важную роль при построении двухзвенных приложений типа клиент/сервер. Мы же создаем трехзвенное приложение. В этом приложении код, описывающий логику представления, которое реализовано с помощью Windows-форм либо Web-форм, взаимодействует с компонентом бизнес-логики, а не непосредственно с базой данных.
Каркас .NET Framework имеет ряд возможностей связывания данных. Они облегчают привязку данных, полученных при помощи промежуточного звена. Очень просто привязать данные к списку массивов (ArrayList). Эта возможность превосходно подходит для нашего примера, потому что мы должны заполнить строками раскрывающийся список (DropDownList) городов, а метод GetCities как раз возвращает список массива строк.
В самой нижней строке уместился весь код, который мы добавили к методу Page_Load класса WebForml, для того, чтобы заполнить раскрывающийся (DropDownList) список listCities.

void Page_Load(Object *sender, System::EventArgs *e)
{
if ( HsPostBack)
{
hotelBroker = new HotelBroker;;
ArrayList *cities = hotelBroker->GetCities(};
listCities->DataSource = cities; // города
ArrayList *hotels = hotelBroker->GetHotels(
dynamic_cast<String *> // Строка
(cities->get_Item(0))); // города
BindHotels(hotels); // гостиницы
DataBind();
}
}

Вызов метода DataBind() связывает все элементы управления сервера с соответствующими им источниками данных. В результате все элементы управления заполняются соответствующими данными. Метод DataBind может быть вызван для каждого элемента управления сервера отдельно. Метод DataBind принадлежит классу Control (Элемент управления). Он наследуется классом Page (Страница) и классами конкретных элементов управления сервера.

Инициализация гостиниц

Аналогично мы можем заполнить второй раскрывающийся список (DropDownList) названиями гостиниц. Но это немного сложнее, потому что GetHotels возвращает список массивов структур HotelListltem, а не строк. Нам необходимо заполнить раскрывающийся список listHotels названиями гостиниц. Здесь нам поможет метод BindHotels, который просматривает в цикле список гостиниц и создает список массивов с названиями гостиниц. Этот список затем привязывается к раскрывающемуся списку listHotels. Ниже приведен законченный код, содержащий логику инициализации гостиниц для первого города (который имеет индекс 0).

void BindHotels(ArrayList *hotels)
{
ArrayList *hotelNames =
new ArrayList(hotels->Count); // гостиницы
lEnumerator *pEnum = hotels->GetEnumerator(); // гостиницы
while (pEnum->MoveNext())
{
HotelListltem *hotel =
dynaraic_cast<HotelListItem *>
(pEnum->Current) ;
hotelNames->Add(hotel->HotelName->Trim());
// Добавить гостиницу;
}
listHotels->DataSource = hotelNames;
}

Выбор города

И, наконец, мы реализуем следующую особенность: при выборе города отображаются гостиницы в выбранном городе. Мы добавляем обработчик события для выбора города. Ниже приведен код для обработки события SelectedlndexChanged.

void listCities_Selected!ndexChanged(
Object *sender, System::EventArgs *e)
{
String *city = listCities->Selected!tem->Text; // Строка
ArrayList *hotels = hotelBroker->GetHotels(city); // город
BindHotels(hotels); // гостиницы
DataBind();
}

Добавление класса Global (Глобальный)

Добавьте к проекту новый файл Global .азах.h. Как обычно, нет необходимости самостоятельно писать соответствующий код. Его можно скопировать из файла решения, который находится в каталоге CaseStudyXAcmeWeb. Для этого выполните следующие пошаговые инструкции:
1. Скопируйте файл Global.asax.h из каталога CaseStudy\AcmeWeb в каталог Demos\AcmeWeb, где расположен новый проект.
2. В окне Solution Explorer (Поиск решения) щелкните правой кнопкой мыши на узле Header Files (Заголовочные файлы) под проектом AcmeWeb, и выберите Add => Add Existing Item (Добавить => Добавить существующий элемент). Затем дважды щелкните на файле Global.азах.h.
Обратите внимание, что в Global.азах.h метод Application_Start создает экземпляр класса HotelBroker и присваивает его статическому полю hotelBroker. Это поле затем извлекается в исходном файле WebForml.aspx.h методом Page_Load, который был приведен ранее.
//Global.asax.h
#using <.\Hotel.dll>
#using <System.dll>
#using <System.Web.dll>
using namespace System;
// использование пространства имен Система;
using namespace OI::NetCpp::Acme;
namespace AcmeWeb
// пространство имен AcmeWeb
{
public _gc class Global :
// класс сборщика мусора Глобальный:
public System::Web::HttpApplication
{
public:
static HotelBroker *hotelBroker; // статическое поле protected: // защищенный
void Application_Start(
Object *sender, EventArgs *e)
{
hotelBroker = new HotelBroker;
}
}; }

Файл Global. asax И Объект Global (Глобальный)

Чтобы вызвать методы класса Global (Глобальный), который определен в файле Global.asax.h, необходим файл Global.азах. Например, если в каталоге AcmeWeb файл Global.asax отсутствует, информационный сервер Internet (US) не сможет вызвать метод Application_Start. А это очень важный метод, так как именно он создает экземпляр класса HotelBroker. Файл Global.азах находится в папке Cas-eStudy\AcmeWeb. Скопируйте этот файл в папку Demos\AcmeWeb. Нет необходимости добавлять его в проект. Но удобства ради мы это сделаем. Чтобы добавить данный файл в проект, выполните следующие пошаговые инструкции.
1. Скопируйте файл Global.азах из каталога CaseStudyXAcmeWeb в каталог DemosXAcmeWeb, в котором расположен ваш новый проект.
2. В окне Solution Explorer (Поиск решения) щелкните правой кнопкой мыши на узле проекта AcmeWeb. Из контекстного меню выберите команду Add (Добавить), затем Add Existing Item (Добавить существующий элемент). Установите *.* в качестве фильтра типа файла, а затем дважды щелкните на файле Global. asax.
Файл Global.asax содержит единственную строку (она приведена ниже), которая указывает, что объект приложения является производным от класса AcmeWeb.Global. Этот класс определен в исходном файле Global. asax. h.

<%@ Application Inherits="AcmeWeb.Global" %>

AcmeWeb.aspx

Другой ASP.NET-файл, который должен обязательно присутствовать в каталоге AcmeWeb, имеет название AcmeWeb. aspx. В этом файле указана сборка, где содержится реализация класса AcmeWeb: :WebForml. Исходный код этого класса содержится в исходном файле WebForml.aspx.h. В файле AcmeWeb.aspx, кроме того, указано, что страница наследует класс AcmeWeb: :WebForml, а также некоторый HTML-код, который предназначен для создания представления, отображаемого для пользователя. Файл AcmeWeb.aspx находится в каталоге CaseStudy\AcmeWeb. Вы можете скопировать его из этого каталога в каталог Demos\AcmeWeb. Добавлять его в проект не обязательно. Но удобства ради мы сделаем это. Чтобы добавить данный файл в проект, выполните следующие пошаговые инструкции:
1. Скопируйте файл AcmeWeb.aspx из каталога 4aseStudy\AcmeWeb в каталог Demos \AcmeWeb, в котором расположен новый пюект
2. В окне Solution Explorer (Поиск решения) щелкште правой кнопкой мыши на узле проекта AcmeWeb Из контекстного меню вьберите команду Add (Добавить), затем Add Existing Item (Добавить существующШ элемент) В качестве фильтра типов файлов используйте * * Затем дважды щелшите на файле AcmeWeb. aspx <!— AcmeWeb.aspx —>

<%@ Assembly Name="AcmeWeb" %>
<%@ Page Inherits=AcmeWeb.WebForml %>
<HTML>
<HEAD>
</HEAD>
<BODY> <'— ТЕЛО —>
<form id="Forml" method="post" runat="servor">
<asp:Label id=Labell style="Z-INDEX: 101; EFT: 52px;
POSITION: absolute; TOP: 84px" runat="serv«r">City</asp:Label>
<' - Город —>
<asp:Label id=Labe!2 style="Z-INDEX: 102, EFT. 55px, POSITION: absolute; TOP: 135px" runat="sener">Hotel</ asp:Label>
Osp.DropDownList id=listCities style="Z-HDEX: 103; LEFT: 134px; POSITION: absolute; TOP: 80px" runa1="server" Width="120px" Height="22px" AutoPostBack="rrue"x/asp: Drop-DownList>
<asp-DropDownList id=listHotels style="Z-I!DEX: 104; LEFT-134px; POSITION: absolute; TOP- 128px" run<t="server" Width="120px" Height="22px"x/asp:DropDown]ist> </form>
</BODY> <<— тело —> </HTML>

Построение AcmeWeb

Чтобы построить проект, скопируйте файл Hotel dll в каталог Demos\AcmeWeb Это необходимо сделать потому, что проект содержит /ирективу #using для указанной сборки Скопировав этот файл из каталога CaseStudy^AcmeWeb, можно построить проект, в результате чего будет создан файл AcmeWeb. dll

Просмотр AcmeWeb

Прежде чем вы сможете просмотреть приложение AcmeWeb в броузере, вам нужно сначала скопировать файл AcmeWeb.dll в подкатало bin каталога \Demos\AcmeWeb Вы уже это делали в случае каталога CaseStudy\Acmefeb
1. В каталоге DemosXAcmeWeb, в котором расположи проект, создайте подкаталог bin
2. Скопируйте файл AcmeWeb dll из каталога Dtmos\AcmeWeb\Debug в каталог Demos\AcmeWeb\bin
3. Кроме того, скопируйте файл Hotel. dll в катаюг Demos\AcmeWeb\bin
Но даже после копирования AcmeWeb. dll в катало bin вы все же не можете отобразить http: //localhost/NetCpp/Demos/AcmeWeb/JcmeWeb.aspx в вашем броузере Ведь для этой Web-страницы нужно еще сконфигур1ровать виртуальный каталог как приложение для информационного сервера Internet (II>) Чтобы сделать это, выполните следующие инструкции
4. Щелкните на кнопке Start (Пуск) и выберите команду Programs (Программы) Затем выберите команду Administrative Tools (Средства администрирования) и запустите Internet Server Manager (Диспетчер серверов Internet)
5. Откройте дерево под стандартным Web-узлом (Default Web Site) до узла NetCpp\Demo s\AcmeWeb
6. Щелкните правой кнопкой мыши на каталоге NetCpp \Demos \AcmeWeb Из контекстного меню выберите команду Properties (Свойства)
7. В диалоговом окне щелкните на кнопке Create (Создать), рис. 10.20.
8. Появится диалоговое окно, показанное на рис. 10.21.
9. Щелкните на кнопке ОК
Только теперь http://localhost/NetCpp/CaseStudy/AcmeWeb/AcmeWeb.aspx можно отобразить в окне броузера (рис. 10.22.) Эту страницу можно отобразить непосредственно в броузере или выполнить ее в Visual Studio, которая вызовет Internet Explorer, чтобы обратиться к приложению по протоколу передачи гипертекстовых файлов HTTP При прокрутке списка городов вы увидите города, возвращенные компонентом HotelBroker



Рис. 10.20. Создание имени приложения (Application Name) для Acme Web

Отладка AcmeWeb

Чтобы отладить проект AcmeWeb, необходимо создать файл конфигурации и в нем определить используемый режим отладки Необходимо также включить режим отладки в проекте, как показано на рис 10 23 Чтобы сделать это, выполните следующие шаги
1. Скопируйте файл Web.config из каталога CaseStudy\AcmeWeb в каталог Demos\AcmeWeb. В этом файле конфигурации можно указать несколько возможностей, но для отладки наиболее важен тэг Compilation debug="tme"/> (<отладка сборки = "истина"/>).
2. В окне Solution Explorer (Поиск решения) щелкните правой кнопкой мыши на проекте AcmeWeb. Из контекстного меню выберите команду Properties (Свойства).
3. В папке Configuration Properties (Свойства конфигурации) щелкните кнопкой мыши на узле Debugging (Отладка).
4. В качестве значения свойства Command (Команда) укажите aspnet_wp. ехе.
5. В качестве значения свойства Attach (Присоединить) укажите Yes (Да).
6. Укажите http: //localhost/NetCpp/Demos/AcmeWeb/AcmeWeb.aspx в качестве значения свойства HTTP URL.
Теперь можно открыть решение в отладчике. Для этого выберите из меню Debug (Отладка) команду Start (Пуск). На рис. 10.24 и рис. 10.25 показан отладчик, остановившийся в точках останова, содержащихся в файлах Global. азах. h и WebForml. aspx. h, соответственно.



Рис. 10.21. Создание имени приложения (Application Name) для AcmeWeb завершено



Приложения ASP.NET

ASP.NET-приложение состоит из всех Web-страниц и файлов с кодом, которые хранятся на Web-сервере в виртуальном каталоге или его подкаталогах. Как мы уже убедились, кроме . aspx-файлов и файлов с фоновым кодом в состав приложения также входят файлы global.азах и config.web. В этом разделе главы мы рассмотрим возможности приложений ASP.NET. Затем мы изучим механизмы, которые обеспечивают работу с состоянием приложения и состоянием сеанса, а также конфигурирование Web-приложений.



Рис. 10.22. При выполнении на Web-странице отображается информация о городах



Сеансы

Чтобы по достоинству оценить поддержку Web-приложений в ASP.NET, нужно иметь четкое представление о концепции Web-сеанса. Протокол передачи гипертекстовых файлов HTTP (HyperText Transfer Protocol) не хранит состояние приложения. Это значит, что не существует прямого способа, при помощи которого можно было бы узнать, исходит последовательность запросов от одного или от разных клиентов. Web-сервер, например информационный сервер Internet (US), может иметь механизм, при помощи которого исходящие от одного клиента запросы объединяются в логический сеанс. Работать с сеансами в ASP.NET очень легко.



Global.asax

В состав ASP.NET-приложения может входить файл Global. asax. В нем содержится код, который обрабатывает события уровня приложения, инициируемые ASP.NET. Этот файл расположен в корневом каталоге приложения. Если файл Global.asax в приложении отсутствует, ASP.NET считает, что обработчики событий уровня приложения не определены.



Рис. 10.23. Разблокирование отладки



Рис. 10.24. В файле Global, asax.h достигнута точка останова



Рис. 10.25. В файле WebForml. aspx. h достигнута точка останова

В данном коде приведены наиболее часто используемые события уровня приложения. Обычно за время существования Web-приложения происходят следующие события

Application_Start Это событие возникает лишь один раз за все время работы приложения, когда создается первый экземпляр класса HttpApplication Приложение запускается первый раз тогда, когда его запускает информационный сервер Internet (I1S) для первого пользователя В обработчике событий можно инициализировать состояние, которое будет использоваться всем приложением Session_Start возникает в начале каждого сеанса На этом этапе можно инициализировать переменные сеанса Application_BeginRequest инициируется в начале каждого отдельного запроса Как правило, обработка запроса производится классом Page (Страница) Application_EndRequest инициируется в конце запроса Session_End инициируется в конце каждого сеанса. Как правило, не нужно освобождать переменные, инициализированные в начале сеанса (при возникновении события Session_Start) Они будут освобождены автоматически в процессе сборки мусора Но если открыт дорогостоящий ресурс, например, соединение с базой данных, тогда при возникновении этого события можно вызвать метод Dispose (Освободить ранее выделенную область памяти) Application_End инициируется в самом конце срока существования приложения, когда удаляется последний экземпляр HttpApplication

Состояния в приложениях ASP.NET

Сохранение состояния при запросах, посылаемых по протоколу передачи гипертекстовых файлов HTTP, — главная проблема в Web-программировании ASP.NET предоставляет для этого несколько удобных функций Необходимо сохранять два типа состояния.

Состояние приложения — глобальная информация, которая совместно используется всеми пользователями Web-приложения Состояние сеанса используется для хранения данных конкретного пользователя, который многократно обращается к Web-приложению

Статические элементы данных

Статические элементы данных класса совместно используются всеми экземплярами класса Следовательно, статические элементы данных могут использоваться для хранения состояния приложения



Объект Application (Приложение)

Глобальная информация приложения хранится во встроенном объекте Application (Приложение), который является экземпляром класса HttpApplicationState. Удобно получать доступ к этому объекту через свойство Application (Приложение) класса Page (Страница) Класс HttpApplicationState содержит словарь в формате "ключ — значение", используемый для хранения как объектов, так и скалярных величин.



Объект Session (Сеанс)

Информация о сеансе индивидуальных пользователей может храниться во встроенном объекте Session (Сеанс), который является экземпляром класса HttpSession-State. Доступ к этому объекту удобно получать с помощью свойства Session (Сеанс) класса Page (Страница) Класс HttpSessionState, аналогично классу HttpApplicationState, имеет словарь в формате "ключ — значение", который можно использовать для хранения как объектов, так и скалярных величин.
При реализации переменных сеанса возникают некоторые интересные вопросы.

Обычно для идентификации сеанса, от которого поступил запрос, используются небольшие фрагменты данных о предыстории обращений данного пользователя к данному Web-серверу, автоматически создаваемые сервером на машине пользователя (cookies). Что делать, если такие фрагменты данных (cookies) не поддерживаются броузером, или отключены пользователем? Поддержка состояния сеанса для многих пользователей влечет накладные расходы. Истекает ли срок действия состояния сеанса после определенного периода времени? Высокопроизводительными Web-узлами используется группа серверов. Каким образом приложение может получить необходимые ему данные, если второй запрос обслуживается не той машиной, которой обслуживался первый запрос?

Состояние сеанса и небольшие фрагменты данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, автоматически создаваемые сервером на машине пользователя (cookies)

По умолчанию небольшие фрагменты данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, автоматически создаваемые сервером на машине пользователя (cookies), в ASP.NET используются для идентификации сеанса, в котором отправлен запрос. Но ASP.NET можно сконфигурировать так, чтобы при выполнении не создавались эти небольшие фрагменты данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, обычно автоматически создаваемые сервером на машине пользователя (cookies). В такой модели идентификатор сеанса (Session ID), который обычно сохраняется в небольшом фрагменте данных о предыстории обращений конкретного пользователя к конкретному WWW-серверу, автоматически создаваемом сервером на машине пользователя (cookie), внедряется в унифицированный указатель информационного ресурса (URL). Конфигурация, где не используются небольшие фрагменты данных о предыстории обращений конкретного пользователя к конкретному Web-серверу, автоматически создаваемые сервером на машине пользователя (cookies), обсуждается в следующем разделе.

Предельное время ожидания для состояния сеанса

По умолчанию, предельное время ожидания для состояния сеанса истекает после 20 минут. Это означает, что если данный пользователь находится в состоянии ожидания (простоя) в течение указанного периода времени, сеанс прекращается, и запрос от клиента теперь будет обрабатываться как запрос от нового пользователя, причем будет создан новый сеанс. Как и другие параметры, предельное время ожидания указывается в файле конфигурации, — это мы обсудим в разделе "Конфигурация ASP.NET".

Хранение состояния сеанса

С помощью модели состояния сеанса, которая отделяет хранение информации от использования сохраненной информации приложениями, ASP.NET полностью решает не только проблему группы серверов, но и много других проблем. Модели состояния позволяют реализовать различные сценарии хранения так, чтобы не затрагивать при этом код приложения. Сервер состояния .NET не имеет "активных" объектов для запросов Вместо этого в конце каждого сетевого запроса все объекты в коллекции сеанса преобразуются в последовательную форму, чтобы запомнить состояние сеанса. Когда тот же самый клиент возвращается к странице, объекты сеанса преобразуются из последовательной формы в параллельную.
По умолчанию, состояния сеанса кэшируются, и поэтому, как правило, хранятся в оперативной памяти Конечно, в конфигурации можно указать, что в качестве кэша следует использовать память определенной машины или же что состояния сеанса нужно сохранять в базе данных SQL-сервера В этих случаях данные не привязаны к определенному серверу, и потому данные сеанса могут безопасно использоваться группой серверов



Конфигурация ASP.NET

Обсуждая состояние сеанса, мы столкнулись с рядом случаев, в которых желательно конфигурировать ASP NET. Существует два типа конфигурации.

Server configuration (Конфигурация сервера). В этой конфигурации определяются стандартные значения параметров, которые будут использоваться всеми ASP NET-приложениями. Application configuration (Конфигурация приложения) В этой конфигурации определяются значения параметров, которые будут использоваться конкретным ASP.NET-приложением.

Файлы конфигурации

Сведения о конфигурации сервера и приложения хранятся в файлах в формате XML. Содержимое файлов можно легко прочесть, и, в случае необходимости, изменить.

Файл конфигурации сервера

Файл конфигурации сервера имеет название machine.config. Этот файл находится в каталоге \WINNT\Microsoft..NET\Framework. Каждая версия платформы .NET имеет свой каталог, в котором хранится файл конфигурации сервера. За счет этого можно одновременно использовать различные версии ASP.NET. Иными словами, вы можете продолжать использовать Web-приложения, которые работают с предыдущей версией платформы .NET, и одновременно разрабатывать приложения, использующие более новую версию.

Файлы конфигурации приложения

Чтобы сохранить значения параметров, которые используются конкретным Web-приложением, в корне виртуального каталога нужно создать файл web. conf ig. Если этот файл отсутствует, будут использоваться значения параметров конфигурации приложения, принятые по умолчанию. Они хранятся в файле machine. conf ig. Если же файл web. conf ig существует, то будут использованы значения параметров, которые содержатся в нем.

Формат файлов конфигурации

Файл web. conf ig, также как и файл machine, conf ig, хранится в формате XML. Файл состоит из разделов. В каждом разделе объединены взаимосвязанные параметры. Чтобы ознакомиться со структурой файла конфигурации и параметрами, значение которых можно изменить, просмотрите файл web. conf ig, он был создан средой Visual Studio, когда мы создавали новый проект ASP.NET Web-приложения.

<?xml version="l.0" encoding="utf-8" ?>
<!— версия = "1.0" KOflnpOBKa="utf-8" —>
<configuration> <!— конфигурация -->
<system.web>
<!— CUSTOM ERROR MESSAGES
Set mode="on" or "remoteonly" to enable custom
error messages, "off" to disable. Add
<error> tags for each of the errors you want to
handle.
-->
<!-- ПОЛЬЗОВАТЕЛЬСКИЕ СООБЩЕНИЯ ОБ ОШИБКАХ
Установите режим набора = "on" или "remoteonly",
чтобы разрешить пользовательские
сообщения об ошибках, "off" чтобы отключить их. Добавьте
тэги <error> (<ошибка>) для каждой из ошибок,
которую вы хотите обрабатывать.
-->
<customErrors
mode="0ff"
/>
<!-- AUTHENTICATION
This section sets the authentication policies of the application.
Possible modes are "Windows", "Forms", "Passport" and "None"
-->
<!-- ОПОЗНАВАНИЕ
Этот раздел устанавливает политику опознавания
приложения. Возможные режимы - "Windows", *
"Forms" ("Формы"), "Passport" ("Паспорт")
и "None" ("Никакой")
—>
<authentication mode="None" />
<!-- режим опознавания = "Никакой" -->
</system.web>
</configuration> <!— конфигурация —>



Дополнительная информация об ASP.NET

Конечно, используя ASP.NET, вы можете реализовать Web-приложение и на языке C++. Но, как мы уже убедились, язык C++ далеко не оптимальный язык для написания кода с целью создания тех элементов Web-приложения, которые используются при визуальном взаимодействии. Для этого гораздо более подходят языки С# и VB.NET. Чтобы узнать больше об ASP.NET, вы можете обратиться к следующим книгам из серии The Integrated .NET Series, выпущенной издательствами Object Innovations и Prentice Hall PTR:

Application Development Using C# and .NET. (Разработка приложений с помощью С# и.NET.) Application Development Using Visual Basic and .NET. (Разработка приложений с помощью Visual Basic и .NET.) Fundamentals of Web Applications Using .NET and XML. (Основные принципы создания Web-приложений с помощью .NET и XML.)

Язык C++ не имеет себе равных при создании вызываемых с Web-страницы эффективных компонентов для вычислительных машин баз данных. Высокопроизводительные Web-приложения на C++ можно создать также и при помощи технологии, которая имеет название ATL Server. Введение в технологию ATL Server содержится в главе 12 "Web-узлы и Web-службы, работающие на основе ATL Server".



В данной главе вы ознакомились

ASP.NET — это унифицированная платформа разработки Web-приложений. Она значительно упрощает реализацию сложных Web-приложений. В данной главе вы ознакомились с основами технологии ASP.NET, а также рассмотрели Web-формы. Web-формы используются для разработки интерактивных Web-узлов. В основе этой модели программирования на языках высокого уровня лежит модель программирования более низкого уровня, известная как модель программирования запросов и ответов. Эта модель широко использовалась в более ранних технологиях создания Web-приложений и ее использование все еще допускается технологией ASP.NET.
В состав среды разработки приложений Visual Studio.NET входит конструктор форм (Form Designer), который поддерживает языки С# и VB.NET. Конструктор форм (Form Designer) позволяет очень легко визуально создавать макеты Web-форм. С помощью конструктора форм (Form Designer) обработчик события формы можно добавить одним щелчком кнопки мыши. К сожалению, в настоящее время конструктор форм (Form Designer) не поддерживает язык C++, и чтобы создать Web-форму на C++, соответствующий код нужно писать самостоятельно.
В следующей главе мы рассмотрим Web-службы, позволяющие создавать объединенные (распределенные) Web-приложения, которые могут быть развернуты в неоднородных (гетерогенных) системах.